home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
ab20
/
ab20_archive
/
utilities
/
file
/
whereis.lzh
/
whereis.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-16
|
20KB
|
726 lines
/***************************************************************************
* Program: Whereis (searches for a filename on your [hard]-disk) *
* Version: 1.22 for AMIGA-Computers. Last-Update: Saturday 16-Feb-1991 *
* Whereis.c by R. Bless 1989/90/91. All Rights reserved! Program (exe) is *
* free distributable. Compilable under Aztec 3.6a. *
* ------------------------------ NOTE :---------------------------------- *
* No redistribution of a changed source and/or executable without *
* permission of the author!!! Please ask me first. See address below. *
* ----------------------------------------------------------------------- *
* I'm fed up with all 'whereis' or 'wo' utilities that I had, because the *
* one is always case sensitive and can't be aborted, the other is *
* horribly slow and can't handle wildcards >:-(! So here is my product *
* which uses no recursive procedures. *
* Written from 17-10-89 to 24-10-89 (first version then addups) *
* (C)opyright by Roland Bless (Byteable Software Products) *
***************************************************************************/
/*
Any comments or bug-reports to:
R o l a n d B l e s s |UUCP/USENET: rob@spirits.ka.sub.org |
Kriegsstrasse 129 |BITNET: UKG5@DKAUNI2.BITNET FAX: +49211623818 |
7500 Karlsruhe - FRG
voice +49 721 857328
Please don't think that I'm not familiar with gotos or breaks and
such things of not structured languages, but I won't go back to
BASIC-Level with a jump here or there and you don't know where you are...
In a mood I just decided to leave these things out... Maybe I should
write in Pascal or Modula? :-) */
/*
future adds
-s|u|D date search
-l list format */
#include <stdio.h>
#include <ctype.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include "date.h" /* my own date function */
#define MAXPATH 256 /* Maximum pathname length */
#define MEMTYPE 0L /* Memtype: Fast or Chipmem */
#define true 1 /* Right boolean values, because */
#define false 0 /* typedef short BOOL, but TRUE= 1L! */
#define ON true
#define OFF false
struct ListType
{
struct FileInfoBlock FIBlock;
struct FileLock *FLock;
struct ListType *prev;
};
/**** external functions & variables ****/
extern int Enable_Abort;
void *Lock();
void *AllocMem();
void *ParentDir();
extern void date();
struct Process *FindTask();
struct MsgPort *CreatePort();
long IsInteractive(), SetSignal();
struct FileHandle *Input(), *Output();
struct FileLock *CurrentDir();
/***** globals *****/
char MPath [256], c, casedep; /* Global PathName (MainPath) */
WORD options= 0; /* options switches */
WORD MPathPos= 0;
struct StandardPacket *packet;
struct MsgPort *replyport, *conid;
struct Process *myprocess;
char *prgname;
enum { CASESENSITIVE=1, DIRSONLY=2, FILESONLY=4, LONGPATH=8 , SIZE=16,
TIME=32, NOSUBDIRS=64, JUMPDIR=128 };
/* switches go here */
enum { NOMEM, NODIR, DESTROYEDENTRY, TOOMANYARGS, WRONGNAME, ILLEGALOPTION,
NOPATTERN, NOINPUT, STRANGE, INFO, USAGE };
/*** ErrorNumbers for ErrorHandle ***/
char *Msg[]=
{ "FATAL ERROR: Not enough memory available!\n",
"ERROR: Can't find that directory or device:",
"ERROR: Destroyed entry! Couldn't examine this '",
"ERROR: Can't handle so many arguments. See usage!\n",
"ERROR: Please no path in the filename/pattern! See usage!\n",
"ERROR: Illegal Option '",
"ERROR: I've no filepattern to search for!\n",
"ERROR: Input must be interactive! \n",
"STRANGE ERROR: Something strange happend...!\n",
"INFO: whereis V1.22 16-Feb-1991 by R. Bless.\n"
}; /* Messages for ErrorHandle/Numbers */
/******************/
long
Chk_Abort()
{
return 0L;
}
void ErrorHandle(ErrMsgNr)
short ErrMsgNr;
{
if (ErrMsgNr != USAGE)
fprintf(stderr, "%s- %s", prgname, Msg[ErrMsgNr]);
else
{
fprintf(stderr, "usage: %s [-acdfijnpst] [dev:path] filename.", prgname);
fprintf(stderr, " Wildcards *,? allowed.\n");
}
}
int SwitchRaw(RawMode)
BOOL RawMode;
{
replyport= (struct MsgPort *) CreatePort(NULL, NULL);
if (!replyport)
return 1;
packet= (struct StandardPacket *)
AllocMem((long)sizeof(*packet),MEMF_PUBLIC | MEMF_CLEAR);
if (!packet)
{
DeletePort(replyport);
return 1;
}
/* init DOS-Packet */
packet->sp_Msg.mn_Node.ln_Name= (char *) &(packet->sp_Pkt); /* link packet- */
packet->sp_Pkt.dp_Link= &(packet->sp_Msg); /* to message */
packet->sp_Pkt.dp_Port= replyport; /* set-up reply port*/
packet->sp_Pkt.dp_Type= ACTION_SCREEN_MODE; /* function */
if (RawMode==ON)
{
packet->sp_Pkt.dp_Arg1= DOSTRUE;
fflush(stdout);
}
else
{
packet->sp_Pkt.dp_Arg1= DOSFALSE;
}
PutMsg(conid,packet); /* send packet */
WaitPort(replyport); /* wait for packet to come back */
GetMsg(replyport); /* pull message */
FreeMem(packet, (long) sizeof(*packet));
DeletePort(replyport);
return 0;
}
void printdate(ds)
struct DateStamp *ds;
{
struct date mydate;
date(&mydate, ds->ds_Days);
fprintf(stdout," %02d-%02d-%02ld %02ld:%02ld:%02ld",
mydate.day, mydate.month, mydate.year-1900,
ds->ds_Minute/60L, ds->ds_Minute%60L, ds->ds_Tick/50L);
}
void Append(s, root) /* Appends the dirname to MPath (MainPath) */
char *s;
BOOL root;
{
int p;
for (p= 0; s[p]!= '\0'; p++)
MPath[MPathPos+p]= s[p];
MPath[MPathPos+p++]= root==true ? ':' : '/';
MPath[MPathPos+p]= '\0';
MPathPos+=p;
}
void InsertPath(s, root) /* Inserts a dirname into MPath */
char *s;
struct FileLock *root;
{
int p,len;
len= strlen(s)+1;
for (p= MPathPos; p >= 0; p--)
MPath[p+len]= MPath[p];
MPathPos+=len;
for (p= 0; s[p] != '\0'; p++)
MPath[p]= s[p];
MPath[p]= root==NULL ? ':' : '/';
}
void Cut() /* Removes the last dirname from MPath */
{
if (MPathPos) --MPathPos;
while (--MPathPos>=0 && MPath[MPathPos] != '/' && MPath[MPathPos] != ':');
MPath[++MPathPos]= '\0';
}
struct FileLock *FindRoot(FL) /* Climbs up to root-directory */
struct FileLock *FL;
{
struct FileLock *PL;
PL= FL;
while (FL= ParentDir(FL))
{
UnLock(PL);
PL=FL;
}
return PL;
}
long GetFullPath(path) /* Get the full pathname */
char *path;
{
struct FileLock *FL, *PL;
struct FileInfoBlock *FIB;
BOOL Error= false;
FIB= (struct FileInfoBlock *)
AllocMem ((long) sizeof(struct FileInfoBlock), MEMTYPE);
if (!FIB)
{
ErrorHandle(NOMEM);
Error= true;
}
else
if (!(FL= (struct FileLock *) Lock(path, (ULONG) ACCESS_READ)))
{
ErrorHandle(NODIR);
fprintf(stderr," %s\n", path);
Error= true;
}
while (FL && !Error)
{
if (!Examine(FL, FIB))
{
ErrorHandle(DESTROYEDENTRY);
fprintf(stderr,"%s'. Very strange!\n", path);
Error= true;
}
else
{
InsertPath(FIB->fib_FileName, PL= ParentDir(FL));
UnLock (FL);
FL= PL;
}
}
if (FIB) FreeMem (FIB,(long) sizeof(struct FileInfoBlock));
if (FL) UnLock (FL);
return Error;
}
/* Wildcard handling, new routine since V1.19 */
BOOL
Match(s, fpat)
register char *s,*fpat;
{
while (*fpat!='\0')
{
if (*fpat == '*')
{
while (*fpat=='*' || *fpat=='?')
{
fpat++; /* skip following wildcards, until letter or \0 */
}
if (*fpat!='\0') /* letter/pattern detected! */
{
while (*s!='\0' && (*s&casedep) != (*fpat&casedep))
s++;
if (*s=='\0') return NULL;
}
else
while (*s!='\0') /* ingore all chars till end */
s++;
}
else
if (*fpat == '?')
{
fpat++; /* Just ignore that char */
if (*s!='\0') s++;
}
else
if ((*s&casedep) == (*fpat&casedep))
{
register char *stmp=s,*ptmp=fpat;
/* test whether sub-string matches or not */
while (*stmp!='\0' && ((*stmp&casedep) == (*ptmp&casedep)))
{
stmp++;ptmp++;
}
if (*stmp=='\0' || *ptmp=='*' || *ptmp=='?' || *ptmp=='\0')
{
fpat=ptmp;s=stmp; /* it does! next wildcard or so... */
}
else
{
s++;
while (*s!='\0' && (*s&casedep) != (*fpat&casedep)) s++;
}
}
else
return false;
}
return (*s=='\0' ? true : false);
}
/* Now comes the main-stuff!!! */
BOOL Search (path, fpat) /* not recursive! */
char *path, *fpat;
{
struct FileLock *FL= NULL;
struct FileInfoBlock *FIB= NULL;
struct ListType *LChainP= NULL, *OldLChainP= NULL;
BOOL Error= false;
char cbuf;
int p;
casedep= (options & CASESENSITIVE) ? 0xFF : 0x5F; /* Mask for match() */
if (!fpat)
{
ErrorHandle(WRONGNAME);
Error= true;
}
else
if (path)
{
if (options & LONGPATH)
Error= GetFullPath(path); /* Full-Pathname */
else
{ /* "short pathname" */
int p;
for (p= 0; path[p]!= '\0'; p++)
MPath[MPathPos+p]= path[p];
if (p>0)
{
p--;
if (MPath[MPathPos+p]!='/' && MPath[MPathPos+p]!=':')
{
p++; MPath[MPathPos+p]= '/';
}
p++;
}
else
MPathPos= 0;
MPath[MPathPos+p]= '\0';
MPathPos+= p;
}
}
if (!Error)
{
LChainP= (struct ListType *)
AllocMem ((long) sizeof(struct ListType), MEMTYPE);
if (!LChainP)
{
ErrorHandle(NOMEM);
Error= true;
}
else
{
FIB= &LChainP->FIBlock;
if (!(FL= (struct FileLock *) Lock(MPath, (ULONG) ACCESS_READ)))
{
ErrorHandle(NODIR);
fprintf(stderr," %s\n", MPath);
Error= true;
}
else
{
if (!path)
FL= FindRoot(FL);
if (!Examine(FL, FIB))
{
ErrorHandle(DESTROYEDENTRY);
fprintf(stderr,"%s'. Very strange!\n", path);
Error= true;
}
else
if (!path) Append(FIB->fib_FileName, true);
if (!Error)
while (FL)
{
while (FL && ExNext(FL, FIB) && !Error)
{
if (Match(FIB->fib_FileName, fpat)) /*Compare filename&pattern*/
{
BOOL found= false;
if (FIB->fib_DirEntryType >= 0L) /** => it is a dirname **/
{
if (!(options & FILESONLY))
{
fprintf(stdout, "%s%s", MPath, FIB->fib_FileName);
if (options & SIZE)
fprintf(stdout, " (dir) ");
if (options & TIME)
printdate(&(FIB->fib_Date));
fprintf(stdout, "\n");
if (options & JUMPDIR)
found= true;
}
}
else /** => it is a filename **/
if (!(options & DIRSONLY))
{
fprintf(stdout, "%s%s", MPath, FIB->fib_FileName);
if (options & SIZE)
fprintf(stdout, " %ld",FIB->fib_Size);
if (options & TIME)
printdate(&(FIB->fib_Date));
fprintf(stdout, "\n");
if (options & JUMPDIR)
found= true;
}
if (found)
{
if (SwitchRaw(ON))
Error= true;
else
{
int c;
fprintf(stderr,"Change to that dir? [yNq]:");
c= getchar();
fprintf(stderr,"%c\n", c);
SwitchRaw(OFF);
if (toupper(c)=='Y')
{
struct FileLock *CDL;
struct CommandLineInterface *CLI;
char *i;
int p;
if (FIB->fib_DirEntryType >= 0L)
Append(FIB->fib_FileName, false);
/* if Directory found append it to mpath, cause we'll: */
/* change the current dir */
CDL=(struct FileLock *) Lock(MPath, (ULONG) ACCESS_READ);
if (!CDL)
{
ErrorHandle(STRANGE);
Error= true;
}
CDL= CurrentDir(CDL);
UnLock(CDL);
/* The new-lock must be retained and can't be unlocked,
the old one must be unlocked */
CLI=(struct CommandLineInterface *)
BADDR(myprocess->pr_CLI);
i= (char *) ((CLI->cli_SetName) << 2);
/* Copy the new name to CLI */
for (p=0; MPath[p]!='\0'; p++)
*(i+p+1)= MPath[p];
if (MPath[p-1]=='/')
{
*i= (char) (p-1);
}
else
*i= (char) p;
if (FIB->fib_DirEntryType >= 0L)
Cut();
Error= true;
}
if (toupper(c)=='Q')
{
Error= true;
fprintf(stdout,"Quit!\n");
}
}
}
}
if (FIB->fib_DirEntryType >= 0L) /* Dirname? Climb down the tree */
{
if (!(options & NOSUBDIRS))
{
Append(FIB->fib_FileName, false);
LChainP->FLock= FL;
LChainP->prev = OldLChainP;
OldLChainP= LChainP;
cbuf= MPath[MPathPos-1]; MPath[MPathPos-1]= '\0';
FL=(struct FileLock *) Lock(MPath, (ULONG) ACCESS_READ);
MPath[MPathPos-1]= cbuf;
if (!FL)
{
ErrorHandle(STRANGE);
Error= true;
}
else
{
LChainP= (struct ListType *) AllocMem
((long) sizeof(struct ListType), MEMTYPE);
if (!LChainP)
{
ErrorHandle(NOMEM);
Error= true;
UnLock(FL); /* Free last Lock */
LChainP= OldLChainP; /* To free the whole list */
FL= OldLChainP->FLock; /* Get actual Lock */
OldLChainP= OldLChainP->prev;
}
else
{
FIB= &LChainP->FIBlock;
Examine(FL, FIB);
}
}
}
}
} /* Climb-up-the-tree section*/
if (SetSignal(NULL, NULL) & (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D))
{
SetSignal(NULL, (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D));
if (!Error)
{
fprintf(stderr, "** BREAK **\n"); /* Just print one break */
Error= true;
}
}
if (LChainP) /* Is there still an entry? */
{
UnLock(FL); /* Free actual Lock */
Cut();
FreeMem (LChainP, (long) sizeof(struct ListType));
if (OldLChainP) /* Get next entry to free,climb up list */
{
FL = OldLChainP->FLock;
FIB= &OldLChainP->FIBlock;
LChainP= OldLChainP;
OldLChainP= OldLChainP->prev;
}
else /* Last entry reached */
{
FL= NULL;
LChainP= NULL;
}
}
else
FL= NULL; /* No more entries? -> leave while loop */
}
}
}
}
if (LChainP) FreeMem (LChainP,(long) sizeof(struct ListType));
if (OldLChainP) FreeMem (OldLChainP,(long) sizeof(struct ListType));
if (FL) UnLock (FL);
return Error;
}
/******* main(), what else? *******/
main(argc, argv)
int argc;
char **argv;
{
int i1, i2, findx= 0;
char *args[2], *patharg=NULL, *filepattern=NULL;
Enable_Abort= 0; /*** No Ctrl-C please!!! ***/
args[0]= args[1]= NULL;
prgname= *argv;
SetSignal(NULL, (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D)); /*** Clear Ctrl-D signal ***/
if (argc == 1)
{
ErrorHandle(USAGE);
exit(RETURN_OK);
}
for (i1= 1; i1 != argc; i1++)
{
if (*argv[i1] == '-')
for (i2= 1; argv[i1][i2] != '\0'; i2++)
{
switch (argv[i1][i2])
{
case 'a': options|= SIZE | TIME;
break;
case 'c': options|= CASESENSITIVE;
break;
case 'd': options|= DIRSONLY;
break;
case 'f': options|= FILESONLY;
break;
case 'i': ErrorHandle(USAGE);
ErrorHandle(INFO);
exit(RETURN_OK);
break;
case 'j': if (IsInteractive(Input()))
{
myprocess= (struct Process *) FindTask(NULL);
conid = (struct MsgPort *) myprocess->pr_ConsoleTask;
/* get con-handler */
options|= (JUMPDIR | LONGPATH);
}
else
{
ErrorHandle(NOINPUT);
exit(RETURN_FAIL);
}
break;
case 'n': options|= NOSUBDIRS;
break;
case 'p': options|= LONGPATH;
break;
case 's': options|= SIZE;
break;
case 't': options|= TIME;
break;
default : ErrorHandle(ILLEGALOPTION);
fprintf(stderr,"%c' !\n", argv[i1][i2]);
ErrorHandle(USAGE);
exit (RETURN_ERROR);
break;
}
}
else
{
if (findx > 1)
{
ErrorHandle(TOOMANYARGS);
exit (RETURN_ERROR);
}
else
{
args[findx]= argv[i1]; findx++;
}
}
}
if (findx==0)
{
ErrorHandle(NOPATTERN);
ErrorHandle(USAGE);
exit(RETURN_ERROR);
}
for (i1= 0; i1 < 2; i1++)
{
if (args[i1] != NULL)
{
for (i2= 0; (c= args[i1][i2]) != '\0' && c != ':' && c != '/';i2++);
if (c != '\0')
patharg= args[i1];
else
filepattern= args[i1];
}
}
if (findx == 2 && !patharg)
{
patharg= args[0];
filepattern= args[1];
}
if (Search(patharg, filepattern) == true)
{
fprintf(stderr, "%s-- Aborted!\n", prgname);
exit(RETURN_ERROR);
}
}